package org.qhhc.bionioaio.nio.client;


import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Formatter;
import java.util.Set;

public class ChatClient {
    private static final String DEFAULT_SERVER_HOST = "127.0.0.1";
    private static final int DEFAULT_SERVER_PORT = 8888;
    private static final String QUIT = "quit";

    private static final int BUFFER = 1024;
    private String host;
    private int port;
    private SocketChannel clientChannel;
    private Selector selector;
    private ByteBuffer reBuffer = ByteBuffer.allocate(BUFFER);
    private ByteBuffer wBuffer = ByteBuffer.allocate(BUFFER);
    private Charset charset = Charset.forName(String.valueOf(StandardCharsets.UTF_8));


    public ChatClient(String host, int port) {
        this.host = host;
        this.port = port;

    }

    public ChatClient() {
        this(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT);
    }

    public boolean readyToQuit(String msg) {
        return QUIT.equals(msg);
    }

    public void close(Closeable cloneable) {
        if (cloneable != null) {


            try {
                cloneable.close();
            } catch (Exception e) {

            }
        }
    }

    public void start() {

        try {
            clientChannel = SocketChannel.open();
            clientChannel.configureBlocking(false);
            selector = Selector.open();
            clientChannel.connect(new InetSocketAddress(host, port));
            while (selector.isOpen()) {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey selectionKey : selectionKeys) {
                   handles(selectionKey);
                }
                selectionKeys.clear();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            close(selector);
        }


    }

    private void handles(SelectionKey selectionKey) throws Exception {
        if (selectionKey.isAcceptable()) {
            SocketChannel channel = (SocketChannel) selectionKey.channel();
            if (channel.isConnectionPending()) {
                channel.finishConnect();
                new Thread(new UserInputHandler(this)).start();

            }
            channel.register(selector,SelectionKey.OP_READ);

        }else  if (selectionKey.isAcceptable()){
            String msg =receive(clientChannel);
            if (msg.isEmpty()){
                close(selector);
            }else {
                System.out.println(msg);
            }
        }
    }
    private String receive(SocketChannel clientChannel)throws  Exception {
        reBuffer.clear();
        while (clientChannel.read(reBuffer) > 0) ;
        reBuffer.flip();
        return String.valueOf(charset.decode(reBuffer));
    }
    public  void send(String msg)throws Exception{
        if (msg.isEmpty())
            return;
        wBuffer.clear();
        wBuffer.put(charset.encode(msg));
        wBuffer.flip();
        while (wBuffer.hasRemaining()){
            clientChannel.write(wBuffer);
        }
        if (QUIT.equals(msg))
            close(selector);
    }

    public static void main(String[] args) {
        ChatClient chatClient= new ChatClient();
        chatClient.start();
    }
}



